//简单的socket 服务器
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	iconv "github.com/djimenez/iconv-go"
	"io/ioutil"
	"net"
	"net/http"
	"os/exec"
	"strings"
	"time"
)

var (
	host   = "127.0.0.1"
	port   = "6666"
	remote = host + ":" + port
	data   = make([]byte, 1024)
)

type good struct {
	Count, Name, Price, id, tid, img string
}

type order struct {
	Id, Imei, Shop_name, Consignee_Name, Consignee_mobile, Consignee_address, Time, Order_sn, Long, Shop_phone, TotalPrice string
	Menu                                                                                                                   []good
}

func main() {
	//设置服务器
	setport()
	//初始化服务器
	listener := initServer(remote)

	for {
		conn, err := listener.Accept()
		checkError(err, "Accept: ")
		go connectionHandler(conn)
	}
}

func setport() {
	/*
		fmt.Println("请输入ip地址:")
		_, err1 := fmt.Scanln(&host)
		if err1 != nil {
			host = "10.0.62.28"
		}
		fmt.Println("请输入端口号:")
		_, err2 := fmt.Scanln(&port)
		if err2 != nil {
			//fmt.Println("输入为空")
			port = "6666"
		}*/

	host = "10.0.62.28"
	port = "6666"
	remote = host + ":" + port
	fmt.Println("服务器配置成功!为您启动服务器...")
}

func initServer(hostAndPort string) *net.TCPListener {
	serverAddr, err := net.ResolveTCPAddr("tcp", hostAndPort)
	checkError(err, "Resolving address:port failed: '"+hostAndPort+"'")
	listener, err := net.ListenTCP("tcp", serverAddr)
	checkError(err, "ListenTCP: ")
	fmt.Println("服务器启动完毕,正在监听: ", listener.Addr().String())
	return listener
}

func connectionHandler(con net.Conn) {
	var req, imei string
	connFrom := con.RemoteAddr().String()
	println("Connection from: ", connFrom)
	defer con.Close()
	for {
		if imei == "" {
			//imei为空说明第一次读取
			length, err := con.Read(data) //conn.Read()会一直占用通道等待对方输入  下面操作都不会执行 直到接收到内容
			if err != nil {
				fmt.Printf("Client %s quit\n", con.RemoteAddr())
				err := con.Close()
				checkError(err, "Close:")
				return
			}

			//服务器记录
			req = string(data[0:length])
			fmt.Printf("From %s said: %v\n", con.RemoteAddr(), req)

			//对客户端的请求进行分析 并且应答
			e := serverAsk(req, con, &imei)
			if e != nil {
				err := con.Close()
				checkError(err, "Close:")
				return
			}
			time.Sleep(2 * time.Second)
		} else {
			//con.Write([]byte("00"))
			e := serverAsk("00", con, &imei)
			if e != nil {
				fmt.Printf("Client %s quit\n", con.RemoteAddr())
				err := con.Close()
				checkError(err, "Close:")
				return
			}
			con.SetReadDeadline(time.Now().Add(60 * time.Second))
			length, err := con.Read(data)
			if err != nil {
				fmt.Printf("Client %s quit\n", con.RemoteAddr())
				err := con.Close()
				checkError(err, "Close:")
				return
			}

			req := string(data[0:length])
			fmt.Printf("From %s said: %v\n", con.RemoteAddr(), req)
			if req != "00" {
				e1 := serverAsk(req, con, &imei)
				if e1 != nil {
					err := con.Close()
					checkError(err, "Close:")
					return
				}
			}

			time.Sleep(5 * time.Second)
		}

	}
}

func serverAsk(str string, con net.Conn, imei *string) error {
	var val error = errors.New("error arg")
	var code string
	if strings.Contains(str, " ") {
		sf := strings.Fields(str)
		if len(sf) != 3 {
			return val
		}
		if len(sf[1]) < 18 {
			return val
		}
		if *imei == "" {
			//第一次请求只做imei赋值 不做应答  应答由以后心跳来做  //那下面的switch无用了 也不是没用 因为第一次使用810 如果两次810就有用 也就说814还是有用的
			//这么做是为了避免重复发两次00
			code = sf[1][0:3]
			*imei = sf[1][3:len(sf[1])]
			return nil
		} else {
			code = sf[1][0:3]
		}
		switch code {
		case "810":
			s, m := h_getData(*imei)
			if s == "" {
				ss := setContent(m)
				_, err1 := con.Write([]byte(ss))
				fmt.Printf("To %s said: %v\n", con.RemoteAddr(), ss)
				return err1
			} else {
				_, err := con.Write([]byte("00"))
				fmt.Printf("To %s said: %v\n", con.RemoteAddr(), "00")
				return err

			}
		case "00": //这个不会出现因为上面分词
			fmt.Println("from client 00 :", *imei)
			//str = "00"
			//当所有协议写完可以用这个 无效命令直接断开连接
			//default:
			//	fmt.Println("wrong code!")
			//	return "false"
		case "815": //订单打印状态
			sta := sf[2][0:1]
			id := sf[2][1 : len(sf[2])-1]
			//接收最后的内容   112345678920        8151355839022517280               01232#
			str := "http://www.wangluocanche.com/index.php?a=index&m=print&id=" + id + "&sta=" + sta //传到服务器时 路径需要改
			_, err := http.Get(str)                                                                  //使用get方法访问
			if err != nil {
				fmt.Println(err)
			}
			return nil
		case "814": //订单机设置状态返回结果

		case "813": //下发订单机设置命令
		case "811": //下发打印订单内容
		default:
			return val
		}
		return nil
	} else if *imei == "" {
		fmt.Printf("Error arg. Client %s quit\n", con.RemoteAddr())
		return val

	} else { //返回00会进入这里
		//fmt.Println("这里是00---", imei)
		s, m := h_getData(*imei)
		//fmt.Println(s, m, "<----")
		//这个判断和上面一样 s=""时就是menu赋值了
		if s == "00" {
			_, err := con.Write([]byte(s))
			fmt.Printf("To %s said: %v\n", con.RemoteAddr(), "00")
			return err
		} else {
			ss := setContent(m)
			_, err1 := con.Write([]byte(ss))
			fmt.Printf("To %s said: %v\n", con.RemoteAddr(), ss)
			return err1
		}
		return nil
	}

}

func checkError(error error, info string) {
	if error != nil {
		panic("ERROR: " + info + " " + error.Error())
	}
}

func f_getData(imei string) (string, order) {
	var strcode string
	var menu order
	cmd := exec.Command("php", "mysql.test.php", imei)
	out, err := cmd.Output()
	if err != nil {
		fmt.Println("Error msg:", err)
	}
	if string(out[6:]) == "error arg" {
		panic(string(out))
	} else if string(out[6:]) == "00" {
		strcode = "00"
	} else {
		var c byte = 123
		ind := bytes.IndexByte(out, c)
		err1 := json.Unmarshal(out[ind:], &menu)
		if err1 != nil {
			fmt.Println("Can't decode json message  :", err1)
		}

	}
	return strcode, menu
}

func h_getData(imei string) (string, order) {
	var strcode string
	var menu order
	str := "http://www.wangluocanche.com/print/mysql.test.php?imei=" + imei
	resp, err := http.Get(str) //使用get方法访问
	if err != nil {
		fmt.Println(err)
	}
	out, err1 := ioutil.ReadAll(resp.Body) //读取流数据

	if err1 != nil {
		fmt.Println("Error msg:", err1)
	}

	//if string(out[6:]) == "error arg" {
	//	panic(string(out))
	//} else
	if string(out[6:]) == "00" {
		strcode = "00"
	} else {
		var c byte = 123
		ind := bytes.IndexByte(out, c)
		err2 := json.Unmarshal(out[ind:], &menu)
		if err2 != nil {
			fmt.Println("Can't decode json message  :", err2)
		}
	}
	return strcode, menu
}

func setContent(m order) string {
	var content, good string
	for _, menu := range m.Menu {
		good += menu.Name + "%%" + "          	      " + menu.Price + "      " + menu.Count + "%%"
	}
	content = "1" + m.Id + ":###"
	content += "%10" + m.Shop_name + "%%"
	content += m.Consignee_mobile + "%%"
	content += "%00%%条目		        		   单价(元)	   数量%%"
	content += "-----------------------%%"
	content += good
	content += "-----------------------%%"
	content += "外送费 0元          合计:" + m.TotalPrice + "元%%"
	content += "-----------------------%%"
	content += "顾客称呼: " + m.Consignee_Name + "%%"
	content += "联系电话: " + m.Consignee_mobile + "%%"
	content += "送货地址: " + m.Consignee_address + "%%"
	content += "订购时间: " + m.Time + "%%"
	content += "订单编号: " + m.Order_sn + "%%"
	length := len(content)

	output, _ := iconv.ConvertString(content, "utf-8", "gb2312")

	or := "1123456789" + string(length) + "        " + "81101   " + output
	return or
}
